#ifndef BUTTON_H
#define BUTTON_H

#include <raylib.h>
#include <actable.h>
#include <string>
#include <functional>
#include <list_selecter.h>

class Button: public Actable
{
private:
    bool isPressed;
    bool isHovered;
    bool clickHandled;
    std::function<void()> onClickCallBack;
protected:
    bool isClicked; // 没测试
public:
    int x, y, width, height;
    Color color;
    bool disable = false;

    Button() = default;
    // Button(const Button &) = delete;
    // Button(Button &&) = delete;

    Button(int x, int y, int width, int height, Color color = GRAY)
        :x(x), y(y), width(width), height(height), color(color),
        isPressed(false), isHovered(false), isClicked(false)
         {}

    Button* setOnClick(std::function<void()> callBack){
        this->onClickCallBack = callBack;
        return this;
    }
public:
    void render(){
        act();
        draw();
    }
protected:
    void act() override {
        isClicked = false;
        color = GRAY;

        Vector2 mousePos = GetMousePosition();
        isHovered = (mousePos.x >= x && mousePos.x <= x + width &&
                     mousePos.y >= y && mousePos.y <= y + height);

        if(isHovered && IsMouseButtonDown(MOUSE_BUTTON_LEFT)){
            if(!isPressed) {
                isPressed = true;
                clickHandled = false;
            }
            else isPressed = false;
            if(!disable)color = BLACK;
        }

        if(!disable && !clickHandled && isHovered && IsMouseButtonReleased(MOUSE_BUTTON_LEFT) && onClickCallBack){
            onClickCallBack();
            isClicked = true;
            clickHandled = true;
        }

    }
    void draw() override {
        DrawRectangle(x,y,width,height,color);
    }
};

class TextButton : public Button
{
private:
    int textWidth;
    int textHeight;
    // custom font
    Font* font;
    bool customFontMode = false;
    int spacing;
public:
    std::string text;
    Color textColor;

    TextButton() = default;
    // TextButton(const TextButton &) = default;
    // TextButton(TextButton &&) = delete;

    TextButton(int x, int y, int width=30, int height=20,const std::string& text="", Color color = GRAY)
    :Button(x,y,width,height,color),text(text), textColor(YELLOW), textWidth(0), textHeight(32),font(nullptr){}

    TextButton(Font* font, int x, int y, int width=30, int height=20,const std::string& text="", int spacing = 0, Color color = GRAY)
    :Button(x,y,width,height,color),text(text), textColor(YELLOW), textWidth(0), textHeight(32),font(font),spacing(spacing){
        customFontMode = true;
    }

    void setText(const std::string& text){
        this->text = text;
        // if(customFontMode)
        //     textWidth = MeasureTextEx(font, text.c_str(), textHeight, spacing).x;
        // else
        //     textWidth = MeasureText(text.c_str(),textHeight);
        // height = textHeight + 20;
    }

    void setTextColor(Color& color){
        this->color = color;
    }

    void render(){
        act();
        draw();
    }

    int getTextWidth(){
        return customFontMode?MeasureTextEx(*font, text.c_str(), textHeight, spacing).x:MeasureText(text.c_str(),textHeight);
    }

    int getTextHeight(){
        return textHeight;
    }

protected:
    void act() override {
        Button::act(); // super
        textWidth = getTextWidth();
    }

    void draw() override {
        Button::draw(); // super
        if(customFontMode)
            DrawTextEx(*font, text.c_str(), Vector2{(float)x + width / 2 - textWidth / 2,(float)y + height / 2 - textHeight / 2}, textHeight, 0, textColor);
        else
            DrawText(text.c_str(),x + width / 2 - textWidth / 2,y + height / 2 - textHeight / 2, textHeight, textColor);
    }
};

class ImageTextButton : public ListSelecterAdapter
{
private:
    int x, y, width, height;
    std::string text;
    Color textColor;
    int textHeight;
    Texture2D texture;
    // select
    bool isSelected;
    std::function<void()> onSelcetClick;
    // click
    bool isHovered;
    bool isPressed;
    bool clickHandled;
    bool disable;
public:
    ImageTextButton(Texture2D texture, const std::string& text="", Color textColor=YELLOW)
    : x(0), y(0), width(30), height(20),
        text(text), textColor(textColor), textHeight(32),
        texture(texture),
        isSelected(false), isHovered(false), isPressed(false), clickHandled(false), disable(false)
    {}

    void render(){
        act();
        draw();
    }

    void select(bool select) override {
        isSelected = select;
    }

    void setOnSelcetClick(std::function<void()> callBack) override{
        onSelcetClick = callBack;
    }

    Texture* getTexture() override {
        return &texture;
    }

    void setAttribute(int x, int y, int width, int height) override{
        this->x = x;
        this->y = y;
        this->width = width;
        this->height = height;
    }

protected:
    void act() override{
        // act
        Vector2 mousePos = GetMousePosition();
        isHovered = (mousePos.x >= x && mousePos.x <= x + width &&
                     mousePos.y >= y && mousePos.y <= y + height);

        if(isHovered && IsMouseButtonDown(MOUSE_BUTTON_LEFT)){
            if(!isPressed) {
                isPressed = true;
                clickHandled = false;
            }
            else isPressed = false;
            // if(!disable)color = YELLOW;
        }

        if(!disable && !clickHandled && isHovered && IsMouseButtonReleased(MOUSE_BUTTON_LEFT) && onSelcetClick){
            onSelcetClick();
            clickHandled = true;
        }
    }

    void draw() override {
        // draw
        if(isSelected)
            DrawRectangle(x-4,y-4,48+8,48+8,RED);
        // 画图像
        // DrawRectangle(x,y,width,height,color);
        DrawTextureEx(texture, {(float)x,(float)y}, 0, 48/texture.width, WHITE);
        // 画文字
        DrawText(text.c_str(), x + 48 + 8, y + height / 2 - textHeight / 2 -8, textHeight, BLACK);        
    }
};

#endif